(function () {
	type test3 = 1 | 2 | 3 | 4 | 5 extends 1 | 2 | 3 ? 1 : 2;

	type Condition<T> = T extends 1 | 2 | 3 ? T : never;

	type Res1 = Condition<1 | 2 | 3 | 4 | 5>; // 1 | 2 | 3

	type Res2 = 1 | 2 | 3 | 4 | 5 extends 1 | 2 | 3 ? 1 | 2 | 3 | 4 | 5 : never; // never

	//记住第一个差异：是否通过泛型参数传入。我们再看一个例子：
	type Naked<T> = T extends boolean ? 'Y' : 'N';
	type Wrapped<T> = [T] extends [boolean] ? 'Y' : 'N';
	type Res3 = Naked<number | boolean>; // "N" | "Y"
	type Res4 = Wrapped<number | boolean>; // "N"
	//你会发现在 Res3 的判断中，其联合类型的两个分支，恰好对应于分别使用 number 和 boolean 去作为条件类型判断时的结果

	type NoDistribute<T> = T & {};
	type Wrapped1<T> = NoDistribute<T> extends [boolean] ? 'Y' : 'N';
	type Res111 = Wrapped1<[boolean]>;

	//通过将参数与条件都包裹起来的方式，我们对联合类型的比较就变成了数组成员类型的比较，在此时就会严格遵守类型层级一文中联合类型的类型判断了（子集为其子类型）。
	type CompareUnion<T, U> = [T] extends [U] ? true : false;
	type CompareRes1 = CompareUnion<1 | 2, 1 | 2 | 3>;
	type CompareRes2 = CompareUnion<1 | 2, 1>; // false

	//另外一种情况则是，当我们想判断一个类型是否为 never 时，也可以通过类似的手段：
	type IsNever<T> = [T] extends [never] ? true : false;

	type IsNeverRes1 = IsNever<never>; // true
	type IsNeverRes2 = IsNever<'lys'>; // false

	type test10 = [any] extends [never] ? 1 : 2;
	type test11 = any extends never ? 1 : 2;

	// any 在直接作为判断参数时、作为泛型参数时都会产生这一效果：
	// 直接使用，返回联合类型
	type Tmp1 = any extends string ? 1 : 2; // 1|2

	type Tmp2<T> = T extends string ? 1 : 2;

	// 通过泛型参数传入，同样返回联合类型
	type Tmp2Res = Tmp2<any>;

	// 如果判断条件是 any，那么仍然会进行判断
	type Special1 = any extends any ? 1 : 2; // 1
	type Special2<T> = T extends any ? 1 : 2;
	type Special2Res = Special2<any>; // 1
	type Special2Res2 = Special2<string>; // 1

	// 而 never 仅在作为泛型参数时才会产生：
	type Tmp3 = never extends string ? 1 : 2; // 1
	type Tmp4<T> = T extends string ? 1 : 2;
	// 通过泛型参数传入，会跳过判断
	type Tmp4Res = Tmp4<never>; // never

	// 如果判断条件是 never，还是仅在作为泛型参数时才跳过判断
	type Special3 = never extends never ? 1 : 2; //1
	type Special4<T> = T extends never ? 1 : 2;
	type Special4Res = Special4<never>; // never;

	//在类型世界中联合类型就像是一个集合一样。通过使用分布式条件类型，我们能轻易地进行集合之间的运算，比如交集：
	type Intersection<A, B> = A extends B ? A : never;
	type IntersectionRes = Intersection<1 | 2 | 3, 2 | 3 | 4>; // 2 | 3
})();
